// 1.什么是迭代器
// 迭代器（Iterator）是一个对象，它允许你遍历一个容器（如数组、集合、字符串等）中的所有元素，
// 而不需要知道容器内部的结构。迭代器提供了一种标准化的访问容器元素的方式，常用于循环遍历数据结构。

// 2.迭代器的基本概念
// 在 JavaScript 中，迭代器是一个具有特定接口的对象，这个接口主要包含一个 next() 方法。
// 每次调用 next() 方法，都会返回一个具有两个属性的对象：

// value：当前迭代到的值。
// done：一个布尔值，表示迭代是否完成。
// 有一个next方法，每次调用都会返回一个结果对象
// 结果对象有两个属性：value和done。value表示下一个将要返回的值，而done是一个布尔状态，
// 表达当前迭代是否已经结束。如果迭代还未完成，则done的值为false, 反之则为true


// 3.什么是可迭代对象
// 具有Symbol.iterator属性的对象，即为可迭代对象。在 ES6 中，所有集合对象，包括数组，字符串，Set集合，Map 集合。

let values = [1,2]
let iterator = values[Symbol.iterator]()
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())

// 可以看到，Symbol.iterator其实就是一个函数，它的返回值是一个特殊的对象，
// 这个对象有两个属性：value和done。当迭代完成时，done的值为true，而其值为undefined。
// 迭代完成后可以继续调用，没有次数的限制，但其返回的结果对象为{value: undefined, done: true}。

// 4.如何模拟实现一个迭代器

// 首先Symbol.iterator是一个函数，它应该接收一个可迭代对象。因此我们可以创建一个函数：
function createIterator(items){
    let i = 0
    // 其次该函数调用的结果会返回一个拥有next方法的函数：
    return {
        next() {
            //而调用该方法会返回一个包含了value和done属性的结果对象。且该结果对象的value是迭代的，而done是表示当前迭代是否完成。
            //因此我们需要一个能够记录当前迭代位置的指针，并且每一次的调用都去移动该指针。
            return i < items.length ? { done: false, vlaue: items[i++] } : { done: true, vlaue: undefined } 
        }
    }
}

let iterator2 = createIterator(['a', 'b', 'c']);
console.log(iterator2.next()) // {value: 1, done: false}
console.log(iterator2.next()) // {value: 2, done: false}
console.log(iterator2.next()) // {value: 3, done: false}
console.log(iterator2.next()) // {value: undefined, done: true}
console.log(iterator2.next()) // {value: undefined, done: true}

// 自定义迭代器

var obj = { 
    a: 1,
    b: 2,
    c: 2
}

obj[Symbol.iterator] = function () {
    const entries = Object.entries(this); // 获取对象的键值对
    let index = 0;
    return {
        next() {
            if (index < entries.length) {
                const [key, value] = entries[index];
                index++;
                return { value: `${key}: ${value}`, done: false };
            } else {
                return { done: true };
            }
        }
    }
}

for (const value of obj) {
    console.log(value);
}
console.log('是否有迭代器', isIterable(obj))





// 5.判断对象是否为可迭代对象
function isIterable(object){
    return typeof object[Symbol.iterator] === 'function'
}

// 6.内置迭代器
// ES6 为集合对象提供了内置迭代器，在大多数情况下我们无须自己手动实现。
// entries(), values(), keys()都会返回一个迭代器，但是它们的表现不同。
// 但要注意虽然字符串也是可迭代对象，但是它没有这三个内置的迭代器方法，不过它可以使用for...of进行迭代。
// entries()，值为键值对的组合
// values()，值为集合的值
// keys()，值为集合的键名

// 7.不同集合类型的默认迭代器
// 如果我们直接使用for...of而不指定迭代器时，不同类型的集合会默认调用不同的迭代器。
// Map的默认迭代器是entries()，也很容易理解，因为对于Map来说，键和值是映射关系。
// 而对于Set和数组集合来说，默认迭代器是values。

